home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 52
/
Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso
/
Aminet
/
game
/
think
/
AmiChess.lha
/
AmiChess
/
src
/
move.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-10-31
|
13KB
|
610 lines
#include <clib/alib_protos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "common.h"
void MakeMove(short side,int *move)
{
BitBoard *a;
short f,t,fpiece,tpiece;
short rookf,rookt,epsq,sq;
short xside;
GameRec *g;
xside=1^side;
f=FROMSQ(*move);
t=TOSQ(*move);
fpiece=cboard[f];
tpiece=cboard[t];
a=&board.b[side][fpiece];
CLEARBIT(*a,f);
SETBIT(*a,t);
CLEARBIT(board.blockerr90,r90[f]);
SETBIT(board.blockerr90,r90[t]);
CLEARBIT(board.blockerr45,r45[f]);
SETBIT(board.blockerr45,r45[t]);
CLEARBIT(board.blockerr315,r315[f]);
SETBIT(board.blockerr315,r315[t]);
cboard[f]=empty;
cboard[t]=fpiece;
GameCnt++;
g=&Game[GameCnt];
g->epsq=board.ep;
g->bflag=board.flag;
g->Game50=Game50;
g->hashkey=HashKey;
g->phashkey=PawnHashKey;
g->mvboard=Mvboard[t];
Mvboard[t]=Mvboard[f]+1;
Mvboard[f]=0;
if(board.ep>-1) HashKey^=ephash[board.ep];
HashKey^=hashcode[side][fpiece][f];
HashKey^=hashcode[side][fpiece][t];
if(fpiece==king) board.king[side]=t;
if(fpiece==pawn)
{
PawnHashKey^=hashcode[side][pawn][f];
PawnHashKey^=hashcode[side][pawn][t];
}
if(tpiece)
{
ExchCnt[side]++;
CLEARBIT(board.b[xside][tpiece],t);
*move|=(tpiece<<15);
HashKey^=hashcode[xside][tpiece][t];
if(tpiece==pawn) PawnHashKey^=hashcode[xside][pawn][t];
board.material[xside]-=Value[tpiece];
if(tpiece!=pawn) board.pmaterial[xside]-=Value[tpiece];
}
if(*move&PROMOTION)
{
SETBIT(board.b[side][PROMOTEPIECE(*move)],t);
CLEARBIT(*a,t);
cboard[t]=PROMOTEPIECE(*move);
HashKey^=hashcode[side][pawn][t];
HashKey^=hashcode[side][cboard[t]][t];
PawnHashKey^=hashcode[side][pawn][t];
board.material[side]+=(Value[cboard[t]]-ValueP);
board.pmaterial[side]+=Value[cboard[t]];
}
if(*move&ENPASSANT)
{
ExchCnt[side]++;
epsq=board.ep+(side==white?-8:8);
CLEARBIT(board.b[xside][pawn],epsq);
CLEARBIT(board.blockerr90,r90[epsq]);
CLEARBIT(board.blockerr45,r45[epsq]);
CLEARBIT(board.blockerr315,r315[epsq]);
cboard[epsq]=empty;
HashKey^=hashcode[xside][pawn][epsq];
PawnHashKey^=hashcode[xside][pawn][epsq];
board.material[xside]-=ValueP;
}
if(*move&(CAPTURE|CASTLING)||fpiece==pawn) Game50=GameCnt;
if(*move&CASTLING)
{
if(t&0x04)
{
rookf=t+1;
rookt=t-1;
}
else
{
rookf=t-2;
rookt=t+1;
}
a=&board.b[side][rook];
CLEARBIT(*a,rookf);
SETBIT(*a,rookt);
CLEARBIT(board.blockerr90,r90[rookf]);
SETBIT(board.blockerr90,r90[rookt]);
CLEARBIT(board.blockerr45,r45[rookf]);
SETBIT(board.blockerr45,r45[rookt]);
CLEARBIT(board.blockerr315,r315[rookf]);
SETBIT(board.blockerr315,r315[rookt]);
cboard[rookf]=empty;
cboard[rookt]=rook;
Mvboard[rookf]=0;
Mvboard[rookt]=1;
HashKey^=hashcode[side][rook][rookf];
HashKey^=hashcode[side][rook][rookt];
board.castled[side]=true;
}
if(side==white)
{
if(fpiece==king&&board.flag&WCASTLE)
{
if(board.flag&WKINGCASTLE) HashKey^=WKCastlehash;
if(board.flag&WQUEENCASTLE) HashKey^=WQCastlehash;
board.flag&=~WCASTLE;
}
else if(fpiece==rook)
{
if(f==H1)
{
if(board.flag&WKINGCASTLE) HashKey^=WKCastlehash;
board.flag&=~WKINGCASTLE;
}
else if(f==A1)
{
if(board.flag&WQUEENCASTLE) HashKey^=WQCastlehash;
board.flag&=~WQUEENCASTLE;
}
}
if(tpiece==rook)
{
if(t==H8)
{
if(board.flag&BKINGCASTLE) HashKey^=BKCastlehash;
board.flag&=~BKINGCASTLE;
}
else if(t==A8)
{
if(board.flag&BQUEENCASTLE) HashKey^=BQCastlehash;
board.flag&=~BQUEENCASTLE;
}
}
}
else
{
if(fpiece==king&&board.flag&BCASTLE)
{
if(board.flag&BKINGCASTLE) HashKey^=BKCastlehash;
if(board.flag&BQUEENCASTLE) HashKey^=BQCastlehash;
board.flag&=~BCASTLE;
}
else if(fpiece==rook)
{
if(f==H8)
{
if(board.flag&BKINGCASTLE) HashKey^=BKCastlehash;
board.flag&=~BKINGCASTLE;
}
else if(f==A8)
{
if(board.flag&BQUEENCASTLE) HashKey^=BQCastlehash;
board.flag&=~BQUEENCASTLE;
}
}
if(tpiece==rook)
{
if(t==H1)
{
if(board.flag&WKINGCASTLE) HashKey^=WKCastlehash;
board.flag&=~WKINGCASTLE;
}
else if(t==A1)
{
if(board.flag&WQUEENCASTLE) HashKey^=WQCastlehash;
board.flag&=~WQUEENCASTLE;
}
}
}
if(fpiece==pawn&&abs(f-t)==16)
{
sq=(f+t)/2;
board.ep=sq;
HashKey^=ephash[sq];
}
else board.ep=-1;
board.side=xside;
HashKey^=Sidehash;
UpdateFriends();
g->move=*move;
}
void UnmakeMove(short side,int *move)
{
BitBoard *a;
short f,t,fpiece,cpiece;
short rookf,rookt,epsq;
short xside;
GameRec *g;
side=1^side;
xside=1^side;
f=FROMSQ(*move);
t=TOSQ(*move);
fpiece=cboard[t];
cpiece=CAPTUREPIECE(*move);
a=&board.b[side][fpiece];
CLEARBIT(*a,t);
SETBIT(*a,f);
CLEARBIT(board.blockerr90,r90[t]);
SETBIT(board.blockerr90,r90[f]);
CLEARBIT(board.blockerr45,r45[t]);
SETBIT(board.blockerr45,r45[f]);
CLEARBIT(board.blockerr315,r315[t]);
SETBIT(board.blockerr315,r315[f]);
cboard[f]=cboard[t];
cboard[t]=empty;
g=&Game[GameCnt];
Mvboard[f]=Mvboard[t]-1;
Mvboard[t]=g->mvboard;
if(fpiece==king)
board.king[side]=f;
if(*move&CAPTURE)
{
ExchCnt[side]--;
SETBIT(board.b[xside][cpiece],t);
SETBIT(board.blockerr90,r90[t]);
SETBIT(board.blockerr45,r45[t]);
SETBIT(board.blockerr315,r315[t]);
cboard[t]=cpiece;
board.material[xside]+=Value[cpiece];
if(cpiece!=pawn)
board.pmaterial[xside]+=Value[cpiece];
}
if(*move&PROMOTION)
{
CLEARBIT(*a,f);
SETBIT(board.b[side][pawn],f);
cboard[f]=pawn;
board.material[side]+=(ValueP-Value[PROMOTEPIECE(*move)]);
board.pmaterial[side]-=Value[PROMOTEPIECE(*move)];
}
if(*move&ENPASSANT)
{
ExchCnt[side]--;
epsq =(side==white?g->epsq-8:g->epsq+8);
SETBIT(board.b[xside][pawn],epsq);
SETBIT(board.blockerr90,r90[epsq]);
SETBIT(board.blockerr45,r45[epsq]);
SETBIT(board.blockerr315,r315[epsq]);
cboard[epsq]=pawn;
board.material[xside]+=ValueP;
}
if(*move&CASTLING)
{
if(t&0x04)
{
rookf=t+1;
rookt=t-1;
}
else
{
rookf=t-2;
rookt=t+1;
}
a=&board.b[side][rook];
CLEARBIT(*a,rookt);
SETBIT(*a,rookf);
CLEARBIT(board.blockerr90,r90[rookt]);
SETBIT(board.blockerr90,r90[rookf]);
CLEARBIT(board.blockerr45,r45[rookt]);
SETBIT(board.blockerr45,r45[rookf]);
CLEARBIT(board.blockerr315,r315[rookt]);
SETBIT(board.blockerr315,r315[rookf]);
cboard[rookf]=rook;
cboard[rookt]=empty;
Mvboard[rookf]=0;
Mvboard[rookt]=0;
board.castled[side]=false;
}
UpdateFriends();
board.side=side;
board.ep=g->epsq;
board.flag=g->bflag;
HashKey=g->hashkey;
PawnHashKey=g->phashkey;
Game50=g->Game50;
GameCnt--;
}
void SANMove(int move,short ply)
{
short piece,side,ambiguous;
short f,t;
BitBoard b;
leaf *node1;
char *s;
side=board.side;
s=SANmv;
f=FROMSQ(move);
t=TOSQ(move);
if(move&CASTLING)
{
if(t==6||t==62) strcpy(s,"O-O");
else strcpy(s,"O-O-O");
return;
}
piece=cboard[f];
side=board.side;
b=board.b[side][piece];
ambiguous=false;
node1=TreePtr[ply];
if(nbits(b)>1)
{
for(node1=TreePtr[ply];node1<TreePtr[ply+1];node1++)
{
if(FROMSQ(node1->move)==f) continue;
if(TOSQ(node1->move)!=t) continue;
if(cboard[FROMSQ(node1->move)]!=piece) continue;
ambiguous=true;
break;
}
}
if(piece==pawn)
{
if(cboard[t]||board.ep==t)
{
*s++=algbrfile[ROW(f)];
*s++='x';
}
strcpy(s,algbr[t]);
s+=2;
if(move&PROMOTION)
{
*s++='=';
*s++=notation[PROMOTEPIECE(move)];
}
}
else
{
*s++=notation[piece];
if(ambiguous)
{
if(ROW(f)==ROW(FROMSQ(node1->move))) *s++=algbrrank[RANK(f)];
else *s++=algbrfile[ROW(f)];
}
if(cboard[t]) *s++='x';
strcpy(s,algbr[t]);
s+=2;
}
MakeMove(side,&move);
if(SqAtakd(board.king[1^side],side))
{
TreePtr[ply+2]=TreePtr[ply+1];
GenCheckEscapes(ply+1);
if(TreePtr[ply+1]==TreePtr[ply+2]) *s++='#';
else *s++='+';
GenCnt-=TreePtr[ply+2]-TreePtr[ply+1];
}
UnmakeMove(1^side,&move);
*s=0;
}
#define ASCIITOFILE(a) ((a)-'a')
#define ASCIITORANK(a) ((a)-'1')
#define ASCIITOSQ(a,b) (ASCIITOFILE(a))+(ASCIITORANK(b))*8
#define ATOH(a)((a)>='a'&&(a)<='h')
#define ITO8(a)((a)>='1'&&(a)<='8')
leaf *ValidateMove(char *s)
{
short f,t,side,rank,file,fileto;
short piece,kount;
char mvstr[64],*p;
char text[100];
BitBoard b;
leaf *n1,*n2;
TreePtr[2]=TreePtr[1];
GenMoves(1);
FilterIllegalMoves(1);
side=board.side;
p=mvstr;
do
{
if(*s!='x'&&*s!='+'&&*s!='=') *p++=*s;
}
while(*s++);
if(mvstr[strlen(mvstr)-1]=='+'||mvstr[strlen(mvstr)-1]=='#'||mvstr[strlen(mvstr)-1]=='=') mvstr[strlen(mvstr)-1]=0;
if(strcmp(mvstr,"O-O")==0||strcmp(mvstr,"o-o")==0||strcmp(mvstr,"0-0")==0)
{
if(side==white)
{
f=4;
t=6;
}
else
{
f=60;
t=62;
}
return IsInMoveList(1,f,t,' ');
}
if(strcmp(mvstr,"O-O-O")==0||strcmp(mvstr,"o-o-o")==0||strcmp(mvstr,"0-0-0")==0)
{
if(side==white)
{
f=4;
t=2;
}
else
{
f=60;
t=58;
}
return IsInMoveList(1,f,t,' ');
}
if(ATOH(mvstr[0])&&ITO8(mvstr[1])&&ATOH(mvstr[2])&&ITO8(mvstr[3]))
{
f=ASCIITOSQ(mvstr[0],mvstr[1]);
t=ASCIITOSQ(mvstr[2],mvstr[3]);
piece=(strlen(mvstr)==5?mvstr[4]:' ');
return IsInMoveList(1,f,t,piece);
}
if(ATOH(mvstr[0]))
{
if(ITO8(mvstr[1]))
{
t=ASCIITOSQ(mvstr[0],mvstr[1]);
f=t+(side==white?-8:8);
if(f>0&&f<64)
{
if(BitPosArray[f]&board.b[side][pawn])
{
if(mvstr[2]) return IsInMoveList(1,f,t,mvstr[2]);
else return IsInMoveList(1,f,t,' ');
}
f=t+(side==white?-16:16);
if(f>0&&f<64)
{
if(BitPosArray[f]&board.b[side][pawn]) return IsInMoveList(1,f,t,' ');
}
}
}
else if(ATOH(mvstr[1])&&ITO8(mvstr[2]))
{
t=ASCIITOSQ(mvstr[1],mvstr[2]);
rank=ASCIITORANK(mvstr[2])+(side==white?-1:1);
f=rank*8+ASCIITOFILE(mvstr[0]);
piece=(strlen(mvstr)==4?mvstr[3]:' ');
return IsInMoveList(1,f,t,piece);
}
else if(ATOH(mvstr[1]))
{
file=ASCIITOFILE(mvstr[0]);
fileto=ASCIITOFILE(mvstr[1]);
b=board.b[side][pawn]&FileBit[file];
if(side==white) b=b>>(fileto<file?7:9);
else b=b<<(fileto<file?9:7);
if(board.ep>-1) b=b&(board.friends[1^side]|BitPosArray[board.ep]);
else b=b&(board.friends[1^side]);
switch(nbits(b))
{
case 0:
return 0;
case 1:
t=leadz(b);
f=t-(side==white?8:-8)+(file-fileto);
piece=(strlen(mvstr)==3?mvstr[2]:' ');
return IsInMoveList(1,f,t,piece);
default:
sprintf(text,"Ambiguous move: %s %s",s,mvstr);
DoMethod(mui_app,MUIM_Chess_ShowThinking,text);
/* DoMethod(mui_app,MUIM_Chess_ShowBoard); */
return 0;
}
}
}
else if(strchr("NBRQK",mvstr[0]))
{
piece=empty;
if(mvstr[0]=='N') piece=knight;
else if(mvstr[0]=='B') piece=bishop;
else if(mvstr[0]=='R') piece=rook;
else if(mvstr[0]=='Q') piece=queen;
else if(mvstr[0]=='K') piece=king;
b=board.b[side][piece];
t=-1;
if(ITO8(mvstr[1]))
{
rank=ASCIITORANK(mvstr[1]);
b&=RankBit[rank];
t=ASCIITOSQ(mvstr[2],mvstr[3]);
}
else if(ATOH(mvstr[1])&&ATOH(mvstr[2]))
{
file=ASCIITOFILE(mvstr[1]);
b&=FileBit[file];
t=ASCIITOSQ(mvstr[2],mvstr[3]);
}
else if(ATOH(mvstr[1])&&ITO8(mvstr[2])) t=ASCIITOSQ(mvstr[1],mvstr[2]);
kount=0;
n1=0;
n2=0;
while(b)
{
f=leadz(b);
CLEARBIT(b,f);
if(n1=IsInMoveList(1,f,t,' '))
{
n2=n1;
kount++;
}
}
if(kount>1)
{
sprintf(text,"Ambiguous move: %s %s",s,mvstr);
DoMethod(mui_app,MUIM_Chess_ShowThinking,text);
/* DoMethod(mui_app,MUIM_Chess_ShowBoard); */
return 0;
}
if(kount==0) return 0;
return n2;
}
return 0;
}
leaf *IsInMoveList(short ply,short f,short t,char piece)
{
leaf *node;
for(node=TreePtr[ply];node<TreePtr[ply+1];node++)
{
if((short)(node->move&0x0FFF)==MOVE(f,t)&&toupper(piece)==notation[PROMOTEPIECE(node->move)]) return node;
}
return 0;
}
short IsLegalMove(int move)
{
short f,t,piece,side;
BitBoard blocker,enemy;
f=FROMSQ(move);
t=TOSQ(move);
if(cboard[f]==empty) return false;
side=board.side;
if(!(BitPosArray[f]&board.friends[side])) return false;
if(BitPosArray[t]&board.friends[side]) return false;
piece=cboard[f];
if((move &(PROMOTION|ENPASSANT))&&piece!=pawn) return false;
if((move&ENPASSANT)&&t!=board.ep) return false;
if((move&CASTLING)&&piece!=king) return false;
blocker=board.blocker;
if(piece==pawn)
{
if((move&ENPASSANT)&&board.ep>-1) enemy=board.friends[1^side]|BitPosArray[board.ep];
else enemy=board.friends[1^side];
if(side==white)
{
if(!(MoveArray[pawn][f]&BitPosArray[t]&enemy)&&!(t-f==8&&cboard[t]==empty)&&!(t-f==16&&RANK(f)==1&&!(FromToRay[f][t]&blocker))) return false;
}
else if(side==black)
{
if(!(MoveArray[bpawn][f]&BitPosArray[t]&enemy)&&!(t-f==-8&&cboard[t]==empty)&&!(t-f==-16&&RANK(f)==6&&!(FromToRay[f][t]&blocker))) return false;
}
}
else if(piece==king)
{
if(side==white)
{
if(!(MoveArray[piece][f]&BitPosArray[t])&&!(f==E1&&t==G1&&board.flag&WKINGCASTLE&&!(FromToRay[E1][G1]&blocker)&&!SqAtakd(E1,black)&&!SqAtakd(F1,black))&&!(f==E1&&t==C1&&board.flag&WQUEENCASTLE&&
!(FromToRay[E1][B1]&blocker)&&!SqAtakd(E1,black)&&!SqAtakd(D1,black))) return false;
}
if(side==black)
{
if(!(MoveArray[piece][f]&BitPosArray[t])&&!(f==E8&&t==G8&&board.flag&BKINGCASTLE&&!(FromToRay[E8][G8]&blocker)&&!SqAtakd(E8,white)&&!SqAtakd(F8,white))&&!(f==E8&&t==C8&&board.flag&BQUEENCASTLE&&
!(FromToRay[E8][B8]&blocker)&&!SqAtakd(E8,white)&&!SqAtakd(D8,white))) return false;
}
}
else
{
if(!(MoveArray[piece][f]&BitPosArray[t])) return false;
}
if(slider[piece])
{
if(FromToRay[f][t]&NotBitPosArray[t]&blocker) return false;
}
return true;
}
static char s[6];
char *AlgbrMove(int move)
{
short f,t;
f=FROMSQ(move);
t=TOSQ(move);
strcpy(s,algbr[f]);
strcpy(s+2,algbr[t]);
if(move&PROMOTION)
{
/* s[4]=lnotation[PROMOTEPIECE(move)]; */
s[4]=notation[PROMOTEPIECE(move)];
s[5]=0;
}
else s[4]=0;
return s;
}